查看原文
其他

ggplot2多维分面多图层对应规则

2017-09-08 杜雨 R语言中文社区

杜雨,EasyCharts团队成员,R语言中文社区专栏作者,兴趣方向为:Excel商务图表,R语言数据可视化,地理信息数据可视化。个人公众号:数据小魔方(微信ID:datamofang) ,“数据小魔方”创始人。


今天只给大家讲一个知识点,是属于ggplot2高阶用法中的分面与多图层关系如何对应,这个用法之前困扰我很久,也是最近帮朋友做东西才发现这个漏洞,于是感觉分享给大家。


ggplot2的多维分面系统非常完美,可以让我们非常方便的将一个多维度的复杂图形按照某个维度的类别进行矩阵化,使得单个类别的信息更加清晰明了,数据呈现直观易懂。


通常我们可以通过如下步骤做出一个基于地理位置的分面图来。


library(ggplot2)       

library(plyr)          

library(maptools)      

library(Cairo)         

library(RColorBrewer)  

library(dplyr)


CHN_adm2 <- readShapePoly("D:/R/rstudy/CHN_adm/CHN_adm2.shp") 

CHN_adm2_1 <- fortify(CHN_adm2)   

data1 <- CHN_adm2@data          

data2 <- data.frame(id=row.names(data1),data1)        

china_map_data <- join(CHN_adm2_1,data2, type = "full") 

dongsansheng <-subset(china_map_data,NAME_1==c("Heilongjiang","Jilin","Liaoning")) 

dongsansheng$NAME_1<-as.character(dongsansheng$NAME_1)


mydata<-read.csv("D:/R/rstudy/State/dongsansheng.csv",header=T)

dongsansheng<-within(dongsansheng,{

NAME_1[NAME_1=="Heilongjiang"]="黑龙江"

NAME_1[NAME_1=="Jilin"]="吉林"

NAME_1[NAME_1=="Liaoning"]="辽宁"

})



ggplot()+ 

geom_polygon(data=dongsansheng,aes(x=long,y=lat,group=group),colour="grey40",fill="white") +

   facet_grid(.~NAME_1,scales = "free")+

   coord_map("polyconic")+

   theme_void(base_size=18)



然而问题来了,以上图形仅仅基于同一个图层进行维度分面,倘若我有如下需求,不仅要对地图进行分面,而且要在单个区域地图上呈现一些点信息、线条的信息,这就意味着我们需要在保持分面的基础上,叠加图层,那么我们给分面函数指定的分面规则是否能够作用于第二个图层呢,或者说想要让分面函数同事控制所有图层应该 如何进行参数设定呢,分面参数的控制权限到底有多高呢?


带着以下疑问,我们先尝试着在原始分面图层的基础上叠加一个散点图层。


midpos <- function(x) mean(range(x,na.rm=TRUE))

centres <- ddply(dongsansheng,.(NAME_2),colwise(midpos,.(long,lat)))

mydata<-mydata%>%merge(centres)

ggplot() +   geom_polygon(data=dongsansheng,aes(x=long,y=lat,group=group),colour="grey40",fill="white") +

   geom_point(data=mydata,aes(x=long,y=lat,size=zhibiao),colour="red",alpha=.5)+

   facet_grid(.~NAME_1,scales = "free")+

   coord_map("polyconic")+

   scale_size_area(max_size=8)+

   theme_void(base_size=18)



然而遗憾的是,我们得到的结果是这样的,分面函数仅仅控制了第一个图层(也就是地图的图层),却对第二个图层(散点图层没有任何影响),这不是我们想要的结果,我们想要的是这个分面参数同事完成地图和散点图的对应区域分割、匹配。


实际上以上结果并不难解释,因为我们在分面参数设定是,参数设置的依据是第一个图层的数据源中的NAME_1字段,但是我们并没有保证第二个图层中有这个同属性,同名称的字段。


事实上为了进行接下来的案例讲解,我确实在散点图的数据源中设定了一个跟多边形(也就是第一个图层)数据源的NAME_1同属性的字段(里面记录的都是类别相同的省份名称),为了对比效果暂时命名为Province。但是分面函数只能在以上两个数据框中找到第一个图层数据源中含有NAME_1变量,而第二个图层的数据源中尽管有同性质的变量,但是名称不同,分面函数是无法识别的,因为忽略了对图层二的分面操作。



接下来我将图层二中的省份名称变量更改为更图层一中名称相同,再看下结果:


mydata<-mydata%>%rename(NAME_1=Province)

ggplot() +

geom_polygon(data=dongsansheng,aes(x=long,y=lat,group=group),colour="grey40",fill="white") +

   geom_point(data=mydata,aes(x=long,y=lat,size=zhibiao),colour="red",alpha=.5)+

   facet_grid(.~NAME_1,scales = "free")+

   coord_map("polyconic")+

   scale_size_area(max_size=8)+

   theme_void(base_size=18)



这下效果一目了然,分面函数很顺利的识别了通过设定的分面依据字段NAME_1,在图层一、图层二中均探测到了同名字段,而且字段结构类别均一致,分面操作成功。


这个知识点相对难理解,属于ggplot2高阶用法中比较深奥的部分,与此相同的还有分面参数的控制权限范围问题,即分面参数的控制权限范围到底有多高,是否可以控制ggplot父函数内设定的同名参数,关于这一点儿,我先挖个坑,以后有时间再填,如果你感兴趣,可以自己通过以上提示,使用今天的案例数据修改参数,自己探索,相信在实践中提升技能,你学到的才是硬实力。



好了干货完了,接下来打一波广告:


之前很多热情的小伙伴儿们一直在问我有木有开课程的打算,因为自己一直在忙,再加上录制课程比较麻烦,一直动没有动静,最近机缘巧合,跟知名的大数据在线分享平台——天善智能有了合作,打算做一个关于ggplot2的微课分享。


课程时长很短,大约两个小时,时间定在9月12日晚8:00~10:00,内容是ggplot2入门,当然我口中的入门你绝对无法从百度、谷歌和知乎的所谓杂货铺里寻到,不过如果你愿意一丝不苟的去阅读源文档,那么我所讲的内容你也许都可以学到,但是基于我一年的高强度实战经验,也许我可以帮你你理解的更更深入一些,不太会讲也不愿意讲天花乱坠的宣传词,不做任何承诺,能学到什么,全凭悟性和造化。


两个小时虽然很短,但是也要赚一口喝水的钱对吧,不然对不起知识,定价19.9


内容吗,无外乎这些:(时间有限不应定能够全部都涉及到)


1、ggplot2图层语法的核心理念

2、ggplot函数与geom_xxx函数间的父子继承关系

3、美学映射参数写在ggplot函数内与写在geom_xxx内的差异

3、美学映射参数写在aes函数内部和写在aes函数外部的差异

4、颜色标度一共有几种类型和写法,在不同模块中是否能够共用

5、如何结合实际业务与引用场景进行颜色标度选择

6、多图层叠加时,如何解决颜色标度冲突的问题

7、分面函数的权限控制

8、主题框架与模块间的继承关系

9、主题函数更新与替换方案

10、图形输出与高清抗锯齿渲染


其实这些问题都是之前我学习过程中走过的弯路,随着练习的案例越来越多,这些问题一步步全都解决了,其实如果你能有心看完我的所有关于ggplot讲解部分,差不多这些问题也都能全部理解。


▼扫码关注,原价19.9元课程免费获得!


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存